GError **error)
{
gboolean ret = FALSE;
+ OstreeRepoFile *repo_dir = NULL;
GError *temp_error = NULL;
GFileInfo *child_info = NULL;
OstreeMutableTree *child_mtree = NULL;
GVariant *xattrs = NULL;
GInputStream *file_input = NULL;
- child_info = g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, error);
- if (!child_info)
- goto out;
-
- modified_info = create_modified_file_info (child_info, modifier);
-
- xattrs = ostree_get_xattrs_for_file (dir, error);
- if (!xattrs)
- goto out;
+ /* We can only reuse checksums directly if there's no modifier */
+ if (OSTREE_IS_REPO_FILE (dir) && modifier == NULL)
+ repo_dir = (OstreeRepoFile*)dir;
- if (!stage_directory_meta (self, modified_info, xattrs, &child_file_checksum,
- cancellable, error))
- goto out;
+ if (repo_dir)
+ {
+ ostree_mutable_tree_set_metadata_checksum (mtree, ostree_repo_file_get_checksum (repo_dir));
+ ostree_mutable_tree_set_contents_checksum (mtree, ostree_repo_file_tree_get_content_checksum (repo_dir));
+ }
+ else
+ {
+ child_info = g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!child_info)
+ goto out;
+
+ modified_info = create_modified_file_info (child_info, modifier);
+
+ xattrs = ostree_get_xattrs_for_file (dir, error);
+ if (!xattrs)
+ goto out;
+
+ if (!stage_directory_meta (self, modified_info, xattrs, &child_file_checksum,
+ cancellable, error))
+ goto out;
+
+ ostree_mutable_tree_set_metadata_checksum (mtree, g_checksum_get_string (child_file_checksum));
- ostree_mutable_tree_set_metadata_checksum (mtree, g_checksum_get_string (child_file_checksum));
-
- g_clear_object (&child_info);
- g_clear_object (&modified_info);
+ g_clear_object (&child_info);
+ g_clear_object (&modified_info);
+ }
dir_enum = g_file_enumerate_children ((GFile*)dir, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
modifier, cancellable, error))
goto out;
}
+ else if (repo_dir)
+ {
+ if (!ostree_mutable_tree_replace_file (mtree, name,
+ ostree_repo_file_get_checksum ((OstreeRepoFile*) child),
+ error))
+ goto out;
+ }
else
{
ot_clear_checksum (&child_file_checksum);
gboolean ret = FALSE;
GChecksum *ret_contents_checksum_obj = NULL;
char *ret_contents_checksum = NULL;
- GHashTable *dir_metadata_checksums;
- GHashTable *dir_contents_checksums;
+ GHashTable *dir_metadata_checksums = NULL;
+ GHashTable *dir_contents_checksums = NULL;
GVariant *serialized_tree = NULL;
GHashTableIter hash_iter;
gpointer key, value;
- dir_contents_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify)g_free, (GDestroyNotify)g_free);
- dir_metadata_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify)g_free, (GDestroyNotify)g_free);
-
- g_hash_table_iter_init (&hash_iter, ostree_mutable_tree_get_subdirs (mtree));
- while (g_hash_table_iter_next (&hash_iter, &key, &value))
+ if (ostree_mutable_tree_get_contents_checksum (mtree))
{
- const char *name = key;
- OstreeMutableTree *child_dir = value;
- char *child_dir_contents_checksum;
+ ret_contents_checksum = g_strdup (ostree_mutable_tree_get_contents_checksum (mtree));
+ }
+ else
+ {
+ dir_contents_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+ dir_metadata_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+
+ g_hash_table_iter_init (&hash_iter, ostree_mutable_tree_get_subdirs (mtree));
+ while (g_hash_table_iter_next (&hash_iter, &key, &value))
+ {
+ const char *name = key;
+ OstreeMutableTree *child_dir = value;
+ char *child_dir_contents_checksum;
- if (!ostree_repo_stage_mtree (self, child_dir, &child_dir_contents_checksum,
- cancellable, error))
- goto out;
+ if (!ostree_repo_stage_mtree (self, child_dir, &child_dir_contents_checksum,
+ cancellable, error))
+ goto out;
- g_hash_table_replace (dir_contents_checksums, g_strdup (name),
- child_dir_contents_checksum); /* Transfer ownership */
- g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
- g_strdup (ostree_mutable_tree_get_metadata_checksum (child_dir)));
- }
+ g_hash_table_replace (dir_contents_checksums, g_strdup (name),
+ child_dir_contents_checksum); /* Transfer ownership */
+ g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
+ g_strdup (ostree_mutable_tree_get_metadata_checksum (child_dir)));
+ }
- serialized_tree = create_tree_variant_from_hashes (ostree_mutable_tree_get_files (mtree),
- dir_contents_checksums,
- dir_metadata_checksums);
+ serialized_tree = create_tree_variant_from_hashes (ostree_mutable_tree_get_files (mtree),
+ dir_contents_checksums,
+ dir_metadata_checksums);
- if (!stage_gvariant_object (self, OSTREE_OBJECT_TYPE_DIR_TREE,
- serialized_tree, &ret_contents_checksum_obj,
- cancellable, error))
- goto out;
- ret_contents_checksum = g_strdup (g_checksum_get_string (ret_contents_checksum_obj));
+ if (!stage_gvariant_object (self, OSTREE_OBJECT_TYPE_DIR_TREE,
+ serialized_tree, &ret_contents_checksum_obj,
+ cancellable, error))
+ goto out;
+ ret_contents_checksum = g_strdup (g_checksum_get_string (ret_contents_checksum_obj));
+ }
ret = TRUE;
ot_transfer_out_value(out_contents_checksum, &ret_contents_checksum);
static char *body;
static char *parent;
static char *branch;
-static gboolean tar;
+static char **trees;
static gint owner_uid = -1;
static gint owner_gid = -1;
{ "metadata-variant", 0, 0, G_OPTION_ARG_FILENAME, &metadata_bin_path, "File containing serialized variant, in host endianness", "path" },
{ "branch", 'b', 0, G_OPTION_ARG_STRING, &branch, "Branch", "branch" },
{ "parent", 'p', 0, G_OPTION_ARG_STRING, &parent, "Parent commit", "commit" },
- { "tar", 0, 0, G_OPTION_ARG_NONE, &tar, "Given arguments are tar files", NULL },
+ { "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &trees, "Overlay the given argument as a tree", "NAME" },
{ "owner-uid", 0, 0, G_OPTION_ARG_INT, &owner_uid, "Set file ownership user id", "UID" },
{ "owner-gid", 0, 0, G_OPTION_ARG_INT, &owner_gid, "Set file ownership group id", "GID" },
{ NULL }
char *contents_checksum = NULL;
GCancellable *cancellable = NULL;
OstreeMutableTree *mtree = NULL;
- int i;
+ char *tree_type = NULL;
context = g_option_context_new ("[ARG] - Commit a new revision");
g_option_context_add_main_entries (context, options, NULL);
mtree = ostree_mutable_tree_new ();
- if (argc == 1)
+ if (argc == 1 && (trees == NULL || trees[0] == NULL))
{
char *current_dir = g_get_current_dir ();
arg = ot_gfile_new_for_path (current_dir);
}
else
{
- for (i = 1; i < argc; i++)
+ const char *const*tree_iter;
+ const char *tree;
+ const char *eq;
+
+ for (tree_iter = (const char *const*)trees; *tree_iter; tree_iter++)
{
+ tree = *tree_iter;
+
+ eq = strchr (tree, '=');
+ if (!eq)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Missing type in tree specification '%s'", tree);
+ goto out;
+ }
+ g_free (tree_type);
+ tree_type = g_strndup (tree, eq - tree);
+ tree = eq + 1;
+
g_clear_object (&arg);
- arg = ot_gfile_new_for_path (argv[i]);
- if (tar)
+ if (strcmp (tree_type, "dir") == 0)
+ {
+ arg = ot_gfile_new_for_path (tree);
+ if (!ostree_repo_stage_directory_to_mtree (repo, arg, mtree, modifier,
+ cancellable, error))
+ goto out;
+ }
+ else if (strcmp (tree_type, "tar") == 0)
{
+ arg = ot_gfile_new_for_path (tree);
if (!ostree_repo_stage_archive_to_mtree (repo, arg, mtree, modifier,
cancellable, error))
goto out;
}
- else
+ else if (strcmp (tree_type, "ref") == 0)
{
+ if (!ostree_repo_read_commit (repo, tree, &arg, cancellable, error))
+ goto out;
+
if (!ostree_repo_stage_directory_to_mtree (repo, arg, mtree, modifier,
cancellable, error))
goto out;
}
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid tree type specification '%s'", tree_type);
+ goto out;
+ }
}
}
g_clear_object (&mtree);
g_free (contents_checksum);
g_free (parent);
+ g_free (tree_type);
if (metadata_mappedf)
g_mapped_file_unref (metadata_mappedf);
if (context)